#include "my_device.h"

#include <stdlib.h> // 添加这个头文件以使用strtol
/**
 * @brief 初始化指定GPIO引脚为输出模式并置低电平
 * 
 * 该函数用于配置GPIO引脚为通用GPIO功能，设置为输出方向，并将初始电平设置为低电平。
 * 适用于需要控制外部设备（如LED、继电器等）的场景。
 * 
 * @param gpio 要初始化的GPIO引脚编号（pin_t类型）
 */
void my_gpio_init(pin_t gpio)
{
    // 设置引脚为GPIO功能模式
    uapi_pin_set_mode(gpio, HAL_PIO_FUNC_GPIO);
    // 配置GPIO为输出方向
    uapi_gpio_set_dir(gpio, GPIO_DIRECTION_OUTPUT);
    // 初始化为低电平
    uapi_gpio_set_val(gpio, GPIO_LEVEL_LOW);
}

/**
 * @brief 读取指定GPIO引脚的输出值
 * 
 * 该函数用于获取指定GPIO引脚当前的输出电平状态，适用于需要读取自身输出状态的场景。
 * 注意：此函数读取的是输出寄存器的值，而非实际引脚的输入值。
 * 
 * @param gpio 要读取的GPIO引脚编号（pin_t类型）
 * @return gpio_level_t 返回引脚的电平状态（GPIO_LEVEL_LOW或GPIO_LEVEL_HIGH）
 */
gpio_level_t my_io_readval(pin_t gpio)
{
    return uapi_gpio_get_output_val(gpio);
}

/**
 * @brief 设置指定GPIO引脚的输出值
 * 
 * 该函数用于控制指定GPIO引脚的输出电平，可直接驱动外部设备的开关状态。
 * 
 * @param gpio 要设置的GPIO引脚编号（pin_t类型）
 * @param level 要设置的电平状态（GPIO_LEVEL_LOW或GPIO_LEVEL_HIGH）
 */
void my_io_setval(pin_t gpio, gpio_level_t level)
{
    uapi_gpio_set_val(gpio, level);
}

// UART相关函数

/**
 * @brief 初始化UART对应的GPIO引脚模式
 * 
 * 根据指定的UART总线编号，配置对应的TX和RX引脚为相应的UART功能模式。
 * 不同总线可能需要不同的引脚模式（如模式1或模式2）。
 * 
 * @param uart_bus UART总线编号（0、1、2）
 * @param uart_tx TX引脚编号（pin_t类型）
 * @param uart_rx RX引脚编号（pin_t类型）
 */
void uart_gpio_init(uint16_t uart_bus, uint16_t uart_tx, uint16_t uart_rx )
{
    // 根据UART总线编号配置引脚模式
    if(uart_bus == 1 || uart_bus == 0){
        uapi_pin_set_mode(uart_tx, PIN_MODE_1);
        uapi_pin_set_mode(uart_rx, PIN_MODE_1);
    }
    else if(uart_bus == 2){
        uapi_pin_set_mode(uart_tx, PIN_MODE_2);
        uapi_pin_set_mode(uart_rx, PIN_MODE_2);
    }
}

/**
 * @brief 初始化UART通信参数配置
 * 
 * 该函数用于配置UART的通信参数（波特率、数据位、停止位、校验位等），并完成UART的初始化。
 * 支持自定义缓冲区配置，适用于需要灵活配置UART通信的场景。
 * 
 * @param uart_bus UART总线编号
 * @param uart_tx TX引脚编号
 * @param uart_rx RX引脚编号
 * @param buff_config UART缓冲区配置结构体指针（可为NULL使用默认配置）
 */
void uart_init_config(uint16_t uart_bus, uint16_t uart_tx, uint16_t uart_rx, uart_buffer_config_t* buff_config)
{
    // 定义UART通信属性结构体并初始化（115200波特率，8位数据位，1位停止位，无校验）
    uart_attr_t attr = {
        .baud_rate = 115200, 
        .data_bits = UART_DATA_BIT_8, 
        .stop_bits = UART_STOP_BIT_1, 
        .parity = UART_PARITY_NONE
    };

    // 配置UART引脚（不使用CTS/RTS流控）
    uart_pin_config_t pin_config = {
        .tx_pin = uart_tx, 
        .rx_pin = uart_rx, 
        .cts_pin = PIN_NONE, 
        .rts_pin = PIN_NONE
    };
    
    // 先反初始化UART，确保干净的初始化环境
    uapi_uart_deinit(uart_bus);
    // 初始化UART
    int ret = uapi_uart_init(uart_bus, &pin_config, &attr, NULL, buff_config);
    if (ret != 0) {
        printf("uart init failed ret = %02x\n", ret);
    }
}

/**
 * @brief 将控制状态信息格式化为字符串消息
 * 
 * 该函数将ControlState结构体中的设备控制状态（ID、各标志位、RGB颜色等）
 * 按照特定格式组装成字符串，用于设备间通信或日志输出。
 * 
 * @param state 指向ControlState结构体的指针，包含设备控制状态信息
 * @param output 输出字符串缓冲区，用于存储格式化后的消息
 * @param max_len 输出缓冲区的最大长度，防止缓冲区溢出
 */
void build_message(const ControlState *state, char *output, size_t max_len) {
    // 格式化消息字符串，格式："fF:X,wF:X,sF:X,swF:X,r:X,g:X,b:X,over"
    snprintf(output, max_len, "%cfF:%c,wF:%c,sF:%c,swF:%c,r:%s,g:%s,b:%s,over",
        state->id[0],               // 设备ID
        state->fanFlag[0],          // 风扇标志位
        state->waterFlag[0],        // 水泵标志位
        state->sunFlag[0],          // 灯光标志位
        state->switchFlag[0],       // 总开关标志位
        state->colorNum[0],         // 红色分量
        state->colorNum[1],         // 绿色分量
        state->colorNum[2]          // 蓝色分量
    );
    // 打印生成的消息用于调试
    osal_printk("build_message:::%s", output);
}

/**
 * @brief 打印设备控制状态信息
 * 
 * 该函数用于将ControlState结构体中的设备控制状态信息格式化输出到控制台，
 * 便于调试和查看设备当前的控制状态。
 * 
 * @param state 指向ControlState结构体的指针，包含设备控制状态信息（为NULL时不打印）
 */
void print_control_state(const ControlState *state) {
    if (state) {  // 检查指针有效性
        osal_printk("Control State - ID: %s\n", state->id);
        osal_printk("  Fan Flag: %s\n", state->fanFlag);       // 风扇状态
        osal_printk("  Water Flag: %s\n", state->waterFlag);   // 水泵状态
        osal_printk("  Sun Flag: %s\n", state->sunFlag);       // 灯光状态
        osal_printk("  Switch Flag: %s\n", state->switchFlag); // 总开关状态
        osal_printk("  RGB Color: %s, %s, %s\n",               // RGB颜色值
                   state->colorNum[0], 
                   state->colorNum[1], 
                   state->colorNum[2]);
    }
}

/*
// 辅助函数：解析布尔值
static void parse_bool_field(char **ptr, char *dest) {
    // 跳过空格和冒号
    while (**ptr && (isspace((unsigned char)**ptr) || **ptr == ':' || **ptr == ',' || **ptr == '}')) {
        (*ptr)++;
    }
    
    if (strncmp(*ptr, "true", 4) == 0) {
        dest[0] = '1';
        dest[1] = '\0'; // 添加终止符
        *ptr += 4;
    } else if (strncmp(*ptr, "false", 5) == 0) {
        dest[0] = '0';
        dest[1] = '\0'; // 添加终止符
        *ptr += 5;
    }
}

// 辅助函数：提取字符串值
static void extract_string_value(char **ptr, char *dest, size_t dest_size) {
    // 跳过空格、冒号和引号
    while (**ptr && (isspace((unsigned char)**ptr) || **ptr == ':' || **ptr == '"' || **ptr == ',' || **ptr == '}')) {
        (*ptr)++;
    }
    
    char *start = *ptr;
    while (**ptr && !isspace((unsigned char)**ptr) && **ptr != ',' && **ptr != '}') {
        (*ptr)++;
    }
    
    size_t len = *ptr - start;
    if (len > 0) {
        len = (len < dest_size - 1) ? len : dest_size - 1;
        memcpy(dest, start, len);
        dest[len] = '\0';
    } else {
        dest[0] = '\0';
    }
}
// 主解析函数（改进版本）
void parse_control_message(ControlState* state, const char *msg) {
    if (!state || !msg) return;
    
    // 不再整体清零，仅在首次使用时初始化
    static int initialized = 0;
    if (!initialized) {
        memset(state, 0, sizeof(ControlState));
        initialized = 1;
    }
    
    char *ptr = (char *)strstr(msg, "\"paras\":");
    if (!ptr) return;
    ptr += 8; // 移动到paras对象开始处

    // 顺序无关的字段解析
    const char *fields[] = {
        "\"gather\"", "\"open_fan\"", "\"open_water\"", 
        "\"open_led\"", "\"led_red\"", "\"led_blue\"", 
        "\"led_green\"", "\"id\"", NULL
    };
    
    for (int i = 0; fields[i]; i++) {
        char *field = strstr(ptr, fields[i]);
        if (!field) continue;
        
        field += strlen(fields[i]); // 移动到字段值位置
        
        if (strcmp(fields[i], "\"gather\"") == 0) {
            parse_bool_field(&field, state->switchFlag);
        } 
        else if (strcmp(fields[i], "\"open_fan\"") == 0) {
            parse_bool_field(&field, state->fanFlag);
        }
        else if (strcmp(fields[i], "\"open_water\"") == 0) {
            parse_bool_field(&field, state->waterFlag);
        }
        else if (strcmp(fields[i], "\"open_led\"") == 0) {
            parse_bool_field(&field, state->sunFlag);
        }
        else if (strcmp(fields[i], "\"led_red\"") == 0) {
            extract_string_value(&field, state->colorNum[0], sizeof(state->colorNum[0]));
        }
        else if (strcmp(fields[i], "\"led_blue\"") == 0) {
            extract_string_value(&field, state->colorNum[1], sizeof(state->colorNum[1]));
        }
        else if (strcmp(fields[i], "\"led_green\"") == 0) {
            extract_string_value(&field, state->colorNum[2], sizeof(state->colorNum[2]));
        }
        else if (strcmp(fields[i], "\"id\"") == 0) {
            extract_string_value(&field, state->id, sizeof(state->id));
        }
    }
}

*/

// 改进parse_control_message函数以处理JSON格式


void parse_control_message(ControlState *state, const char *message) {
    const char *ptr = message;       // 解析指针
    char *endptr = NULL;             // strtol函数的结束指针
    long temp_value;                 // 临时存储解析的数值

    // 提取"gather"字段（总开关状态），转换为'1'（开）或'0'（关）
    ptr = strstr(ptr, "\"gather\":");
    if (ptr) {
        ptr += strlen("\"gather\":");
        state->switchFlag[0] = (strncmp(ptr, "true", 4) == 0) ? '1' : '0';
    }

    // 提取"open_fan"字段（风扇状态）
    ptr = strstr(message, "\"open_fan\":");
    if (ptr) {
        ptr += strlen("\"open_fan\":");
        state->fanFlag[0] = (strncmp(ptr, "true", 4) == 0) ? '1' : '0';
    }

    // 提取"open_water"字段（水泵状态）
    ptr = strstr(message, "\"open_water\":");
    if (ptr) {
        ptr += strlen("\"open_water\":");
        state->waterFlag[0] = (strncmp(ptr, "true", 4) == 0) ? '1' : '0';
    }

    // 提取"open_led"字段（灯光状态）
    ptr = strstr(message, "\"open_led\":");
    if (ptr) {
        ptr += strlen("\"open_led\":");
        state->sunFlag[0] = (strncmp(ptr, "true", 4) == 0) ? '1' : '0';
    }

    // 提取"led_red"字段（红色分量），转换为字符串存储
    ptr = strstr(message, "\"led_red\":");
    if (ptr) {
        ptr += strlen("\"led_red\":");
        temp_value = strtol(ptr, &endptr, 10); // 字符串转长整数
        snprintf(state->colorNum[0], sizeof(state->colorNum[0]), "%ld", temp_value);
    }

    // 提取"led_green"字段（绿色分量）
    ptr = strstr(message, "\"led_green\":");
    if (ptr) {
        ptr += strlen("\"led_green\":");
        temp_value = strtol(ptr, &endptr, 10);
        snprintf(state->colorNum[1], sizeof(state->colorNum[1]), "%ld", temp_value);
    }

    // 提取"led_blue"字段（蓝色分量）
    ptr = strstr(message, "\"led_blue\":");
    if (ptr) {
        ptr += strlen("\"led_blue\":");
        temp_value = strtol(ptr, &endptr, 10);
        snprintf(state->colorNum[2], sizeof(state->colorNum[2]), "%ld", temp_value);
    }

    // 提取"id"字段（设备ID），转换为字符串存储
    ptr = strstr(message, "\"id\":");
    if (ptr) {
        ptr += strlen("\"id\":");
        
        // 跳过可能的空格和引号
        while (*ptr == ' ' || *ptr == '\"') ptr++;
        
        // 转换为整数
        temp_value = strtol(ptr, &endptr, 10);
        
        // 检查转换是否有效
        if (endptr != ptr) {
            osal_printk("Parsed id: %ld\r\n", temp_value);
            // 存储为1位数字的字符串
            snprintf(state->id, sizeof(state->id), "%01ld", temp_value);
        } else {
            osal_printk("Failed to parse id: %s\r\n", ptr);
        }
    }
}

/**
 * @brief 智能更新传感器数据（仅更新有效字段）
 * 
 * 该函数用于合并传感器数据，仅将新数据中有效（非空）的字段更新到设备的当前数据中，
 * 适用于增量更新场景，避免覆盖未更新的有效数据。
 * 
 * @param device 指向当前传感器数据结构体的指针（要更新的目标）
 * @param new_data 指向新传感器数据结构体的指针（包含待更新的字段）
 */
void update_device_data(SensorData *device, const SensorData *new_data) {
    // 只更新非空字段
    if (strlen(new_data->humidity) > 0) 
        strcpy(device->humidity, new_data->humidity);
    if (strlen(new_data->temperature) > 0) 
        strcpy(device->temperature, new_data->temperature);
    if (strlen(new_data->ligBuffer) > 0) 
        strcpy(device->ligBuffer, new_data->ligBuffer);
    if (strlen(new_data->soilHum) > 0) 
        strcpy(device->soilHum, new_data->soilHum);
    if (strlen(new_data->uv) > 0) 
        strcpy(device->uv, new_data->uv);
    if (strlen(new_data->rain) > 0) 
        strcpy(device->rain, new_data->rain);
    if (strlen(new_data->co2) > 0) 
        strcpy(device->co2, new_data->co2);
}

/**
 * @brief 智能更新控制状态数据（仅更新有效字段）
 * 
 * 该函数用于合并控制状态数据，仅将新数据中有效（非空）的字段更新到当前控制状态中，
 * 适用于增量控制命令的处理。
 * 
 * @param con 指向当前控制状态结构体的指针（要更新的目标）
 * @param new_data 指向新控制状态结构体的指针（包含待更新的字段）
 */
void update_con_data(ControlState *con, const ControlState *new_data) {
    // 只更新非空字段
    if (strlen(new_data->id) > 0) 
        strcpy(con->id, new_data->id);
    if (strlen(new_data->fanFlag) > 0) 
        strcpy(con->fanFlag, new_data->fanFlag);
    if (strlen(new_data->waterFlag) > 0) 
        strcpy(con->waterFlag, new_data->waterFlag);
    if (strlen(new_data->sunFlag) > 0) 
        strcpy(con->sunFlag, new_data->sunFlag);
    if (strlen(new_data->switchFlag) > 0) 
        strcpy(con->switchFlag, new_data->switchFlag);
    if (strlen(new_data->colorNum[0]) > 0) 
        strcpy(con->colorNum[0], new_data->colorNum[0]);
    if (strlen(new_data->colorNum[1]) > 0) 
        strcpy(con->colorNum[1], new_data->colorNum[1]);
    if (strlen(new_data->colorNum[2]) > 0) 
        strcpy(con->colorNum[2], new_data->colorNum[2]);
}

/**
 * @brief 打印传感器数据信息
 * 
 * 该函数用于将SensorData结构体中的各类传感器数据（温度、湿度、光照等）
 * 格式化输出到控制台，便于调试和数据监控。
 * 
 * @param data 指向SensorData结构体的指针，包含传感器数据（为NULL时输出错误信息）
 */
void print_sensor_data(const SensorData *data) {
    if (data == NULL) {
        printf("Error: NULL SensorData pointer\r\n");
        return;
    }
    
    printf("Sensor Data (ID=%d):\r\n", data->id);
    printf("  - Light:      %s\r\n", data->ligBuffer);       // 光照数据
    printf("  - Humidity:   %s%%\r\n", data->humidity);      // 湿度数据
    printf("  - Temperature: %s°C\r\n", data->temperature);  // 温度数据
    printf("  - Soil Humidity: %s%%\r\n", data->soilHum);    // 土壤湿度数据
    printf("  - UV:         %s\r\n", data->uv);              // 紫外线数据
    printf("  - Rain:       %s\r\n", data->rain);            // 雨水数据
    printf("  - CO2:        %s ppm\r\n", data->co2);         // CO2浓度数据
}

/**
 * @brief 发送指令并等待响应（简化版，不依赖系统时间）
 * 
 * 该函数通过UART发送指令，并尝试多次读取响应，直到获取到响应或达到最大尝试次数。
 * 适用于需要同步通信的场景（如设备指令交互）。
 * 
 * @param req 要发送的指令字符串
 * @param req_len 指令的长度（字节数）
 * @param response 用于存储响应的缓冲区
 * @param max_response_len 响应缓冲区的最大长度（防止溢出）
 * @param max_attempts 最大尝试读取响应的次数
 * @return int 成功返回读取的字节数，失败返回-1
 */
int send_command_and_wait_response(const char *req, size_t req_len, 
                                  uint8_t *response, size_t max_response_len,
                                  int max_attempts) {
    int bytes_read = 0;  // 已读取的总字节数
    int attempt = 0;     // 当前尝试次数
    
    // 发送指令（通过UART总线）
    if (uapi_uart_write(CONFIG_LORA_UART_BUS, (const uint8_t *)req, 
                        (uint32_t)req_len, 0) != (int32_t)req_len) {
        osal_printk("Error: Failed to send command via UART\r\n");
        return -1;
    }
    
    osal_printk("Command sent via UART: %s\r\n", req);
    
    // 清空接收缓冲区
    memset(response, 0, max_response_len);
    
    // 循环尝试读取响应
    while (attempt < max_attempts) {
        // 读取UART数据（存储到response缓冲区的剩余空间）
        int bytes_available = uapi_uart_read(CONFIG_LORA_UART_BUS, 
                                            (uint8_t *)(response + bytes_read), 
                                            (uint32_t)(max_response_len - bytes_read), 
                                            0);
        
        if (bytes_available > 0) {
            bytes_read += bytes_available;
            osal_printk("Received %d bytes via UART (total: %d)\r\n", 
                       bytes_available, bytes_read);
            
            // 检查是否接收到结束标志（回车换行）或缓冲区已满
            char *resp_char = (char *)response;
            if (strstr(resp_char, "\r\n") != NULL || 
                bytes_read >= (ssize_t)(max_response_len - 1)) {
                break;
            }
        }
        
        // 简单延时（通过空循环实现，避免依赖系统定时器）
        for (int i = 0; i < 1000000; i++);
        attempt++;
    }
    
    // 检查是否成功读取到响应
    if (bytes_read == 0) {
        osal_printk("Error: No response received via UART after %d attempts\r\n", 
                   max_attempts);
        return -1;
    }
    
    osal_printk("UART response received: %s\r\n", (char *)response);
    return bytes_read;
}